#include "connectionplayer.h"

ConnectionPlayer::ConnectionPlayer(QHostAddress a, quint16 p, bool onlyReceive) :
	Connection(a, p, onlyReceive)
{
	dirs.clear();
	/*dirs.append(0);
	 dirs.append(0);*/
	isAlive = false;
	speed = 3.0;
	playerTime = 0;
}

ConnectionPlayer::ConnectionPlayer(bool onlyReceive) :
	Connection(onlyReceive)
{
	dirs.clear();
	/*dirs.append(0);
	 dirs.append(0);*/
	isAlive = false;
	speed = 3.0;
	playerTime = 0;
}

QPointF ConnectionPlayer::getVelocityByDirs(quint8 dir1, quint8 dir2)
{
	int count = 0;
	if (dir1 != 0) count++;
	if (dir2 != 0) count++;

	qreal speed_fix = getSpeed();
	qreal dx = 0.0;
	qreal dy = 0.0;

	if (count == 2)
		speed_fix = (getSpeed() * sqrt(2)) / 2;

	for (int i = 0; i < count; i++)
	{
		switch (dir[i])
		{
		case 1://W
			dy -= speed_fix;
			break;
		case 2://D
			dx += speed_fix;
			break;
		case 3://S
			dy += speed_fix;
			break;
		case 4://A
			dx -= speed_fix;
			break;
		default:
			break;
		}
	}
	return QPointF(dx, dy);
}

void ConnectionPlayer::updatePlayerByDelta(quint32 delta)
{
	dir[0] = 0;
	dir[1] = 0;
	bool wasOdd = false;
	int count = 0;
	for (int i = 0; (i < dirs.size()) && count < 2; ++i)
	{
		if (count == 0)
		{
			dir[count] = dirs[i];
			wasOdd = (dir[count] % 2) == 1;
			count++;
		}
		else
		{
			if ((dirs[i] % 2) != wasOdd)
			{
				dir[count] = dirs[i];
				count++;
			}
			else
			{
				continue;
			}
		}
	}

	setVelocity(getVelocityByDirs(dir[0],dir[1])*delta);
}

void ConnectionPlayer::playerTimeTick()
{

	if (getIsAlive())
	{
		bool addImput = true;
		if (getIsRemote())
		{
			for (int i = playerMoveList.count()-1; i >= 0; i--)
			{
				//if (getIsRemote() && getPlayerId()==1) qDebug() << getPlayerTime() << i << playerMoveList.at(i).getTime();
				if (getPlayerTime() >= playerMoveList.at(i).getTime())
				{
					setDirs(playerMoveList.at(i).getPlayerInput().getDir1(), playerMoveList.at(i).getPlayerInput().getDir2());
					setAngle(playerMoveList.at(i).getPlayerInput().getAngle());
					addImput = false;
					break;
				}
			}
		}

		updatePlayerByDelta(1);

		PlayerInput playerInput;
		playerInput.setDir1(dir[0]);
		playerInput.setDir2(dir[1]);
		playerInput.setAngle(getAngle());
		playerInput.setIsShooting(getIsShooting());

		PlayerState playerState;
		playerState.setIsAlive(getIsAlive());
		playerState.setPosition(getPos());
		playerState.setVelocity(getVelocity());

		PlayerMove playerMove;
		playerMove.setTime(getPlayerTime());
		playerMove.setPlayerInput(playerInput);
		playerMove.setPlayerState(playerState);
		//if (getIsRemote()) qDebug() << addImput << playerMoveList.count();
		if (addImput) playerMoveList.append(playerMove);

		//qDebug()<<"client: " << playerMove.getTime() << playerState.getPosition() << playerState.getVelocity();

		if (playerMoveList.count()>100)
		{
			playerMoveList.remove(0,playerMoveList.count()-100);
		}

		emit
		newInputAdded();

		increasePlayerTime();
	}
	else if (!getIsRemote())
	{
		deadPlayerTimeTick();
	}
}

void ConnectionPlayer::receiveInput(quint32 time, PlayerInput& playerInput)
{
	if (time > this->getPlayerTime())
	{
		quint32 deltaTime = time - this->getPlayerTime();

		this->setDirs(playerInput.getDir1(), playerInput.getDir2());

		this->setAngle(playerInput.getAngle());

		this->updatePlayerByDelta(deltaTime);

		movePlayerBy(getVelocity());

		this->setIsShooting(playerInput.getIsShooting());

		this->setPlayerTime(time);

		if (getIsShooting())
		{
			emit gunFired(getPos().x(),getPos().y(),getAngle());
		}
	}
}

void ConnectionPlayer::deadPlayerTimeTick()
{
	//qDebug() << "emit dead time";
	emit deadTimeTick();
}

void ConnectionPlayer::emitGunFired(qreal x, qreal y, qreal angle)
{
	emit gunFired(x,y,angle);
}

void ConnectionPlayer::increasePlayerTime()
{
	playerTime++;
}

void ConnectionPlayer::setNick(QString n)
{
	nick = n;
}

void ConnectionPlayer::setScore(quint16 s)
{
	score = s;
}

void ConnectionPlayer::setPlayerId(quint8 id)
{
	player_id = id;
}

void ConnectionPlayer::setPosition(QPointF p)
{

	if (pos != p)
	{
		pos = p;
		emit positionChanged();
	}
}

bool ConnectionPlayer::movePlayerBy(qreal dx, qreal dy)
{
	if (dx != 0 || dy != 0)
	{
		setPosition(getPos() + QPointF(dx,dy));
		return true;
	}
	return false;
}

bool ConnectionPlayer::movePlayerBy(QPointF v)
{
	return movePlayerBy(v.x(), v.y());
}

void ConnectionPlayer::setVelocity(QPointF vel)
{
	velocity = vel;
}

void ConnectionPlayer::setIsAlive(bool ia)
{
	if (isAlive != ia)
	{
		isAlive = ia;
	}
}

void ConnectionPlayer::setIsReloading(bool isr)
{
	if (isReloading != isr)
	{
		isReloading = isr;

	}
}

void ConnectionPlayer::setIsShooting(bool iss)
{
	isShooting = iss;
}

void ConnectionPlayer::setAngle(qreal a)
{
	if (angle != a)
	{
		angle = a;

	}
}

void ConnectionPlayer::setHealth(qreal h)
{
	health = h;
}

void ConnectionPlayer::setDirs(quint8 d1, quint8 d2)
{
	dirs.clear();
	if (d1 != 0) dirs.append(d1);
	if (d2 != 0) dirs.append(d2);
	dir[0] = d1;
	dir[1] = d2;
}

void ConnectionPlayer::setUsesMouse(bool um)
{
	usesMouse = um;
}
void ConnectionPlayer::setIsRemote(bool ir)
{
	isRemote = ir;
}

void ConnectionPlayer::decreaseHealth(qreal h)
{
	setHealth(getHealth() - h);
	if (getHealth() <= 0)
	{

		if (getIsRemote())
		{
			setDeathTime(time(0));
			setIsAlive(false);
		}
	}
}

QString ConnectionPlayer::getNick()
{
	return nick;
}

quint16 ConnectionPlayer::getScore()
{
	return score;
}

quint8 ConnectionPlayer::getPlayerId()
{
	return player_id;
}

QPointF ConnectionPlayer::getPos()
{
	return pos;
}

QPointF ConnectionPlayer::getVelocity()
{
	return velocity;
}

bool ConnectionPlayer::getIsAlive()
{
	return isAlive;
}

bool ConnectionPlayer::getIsReloading()
{
	return isReloading;
}

bool ConnectionPlayer::getIsShooting()
{
	return isShooting;
}

qreal ConnectionPlayer::getAngle()
{
	return angle;
}

qreal ConnectionPlayer::getSpeed()
{
	return speed;
}

qreal ConnectionPlayer::getHealth()
{
	return health;
}

bool ConnectionPlayer::getUsesMouse()
{
	return usesMouse;
}
bool ConnectionPlayer::getIsRemote()
{
	return isRemote;
}

quint32 ConnectionPlayer::getDeathTime()
{
	return deathTime;
}

void ConnectionPlayer::setDeathTime(quint32 dt)
{
	deathTime = dt;
}

void ConnectionPlayer::setPlayerTime(quint32 pt)
{
	playerTime = pt;
}

quint32 ConnectionPlayer::getPlayerTime()
{
	return playerTime;
}

QVector<PlayerMove> &ConnectionPlayer::getPlayerMoveList()
{
	return playerMoveList;
}

